package com.xzy.aspect;

import com.xzy.annotaion.CheckDataPermission;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Enumeration;

/**
 * @author xzy.xiao
 * @date 2023/6/16  14:23
 */
@Slf4j
@Aspect
@Component
public class CheckDataPermissionAspect {

    @Pointcut("@annotation(com.xzy.annotaion.CheckDataPermission)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object checkDataPermission(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取请求头信息
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            log.info("Annotation Info - {}: {}", headerName, headerValue);
        }

        // 获取注解信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        CheckDataPermission annotation = method.getAnnotation(CheckDataPermission.class);
        String dataType = annotation.dataType();
        String primaryKeyField = annotation.primaryKeyField();
        Class<?> paraClass = annotation.paraClass();
        log.info("Annotation Info - dataType: {}, primaryKeyField: {}, paraClass: {}", dataType, primaryKeyField, paraClass);

        // 获取参数信息
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            log.info("Method Parameters - {}", arg);
            if (paraClass == arg.getClass()) {
                Object fieldValue = getFieldValue(arg, annotation.primaryKeyField());
                System.out.println(fieldValue);
            }
        }

        return joinPoint.proceed();
    }

    private Object getFieldValue(Object object, String fieldName) throws NoSuchFieldException, IllegalAccessException {
        Field field = null;

        Class<?> currentClass = object.getClass();
        while (currentClass != null) {
            try {
                field = currentClass.getDeclaredField(fieldName);
                break;
            } catch (NoSuchFieldException e) {
                currentClass = currentClass.getSuperclass();
            }
        }

        if (field == null) {
            throw new NoSuchFieldException(fieldName);
        }

        field.setAccessible(true);
        return field.get(object);
    }
}
